home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d4 / Telnet2.6.1d4.src.sit.hqx / Telnet 2.6.1d4 source / source / vs / drag.c next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  10.4 KB  |  393 lines

  1. /****************************************************************
  2. *    NCSA Telnet for the Macintosh                                *
  3. *                                                                *
  4. *    National Center for Supercomputing Applications                *
  5. *    Software Development Group                                    *
  6. *    152 Computing Applications Building                            *
  7. *    605 E. Springfield Ave.                                        *
  8. *    Champaign, IL  61820                                        *
  9. *                                                                *
  10. *    Copyright (c) 1986-1994,                                    *
  11. *    Board of Trustees of the University of Illinois                *
  12. ****************************************************************/
  13.  
  14. #include <Drag.h>
  15. #include <GestaltEqu.h>
  16. #include <FragLoad.h>
  17.  
  18. #include "TelnetHeader.h"
  19. #include "wind.h"
  20.  
  21. #include "maclook.proto.h"        // For WindowPtr2WindRecPtr proto
  22. #include "rsmac.proto.h"
  23. #include "parse.proto.h"
  24. #include "drag.proto.h"
  25.  
  26. #ifdef MPW
  27. #pragma segment RS
  28. #endif
  29.  
  30. Boolean    gHaveDragMgr, gDropcanAcceptItems, gDropcursorInContent, gDropDestCanAcceptItems;
  31.  
  32. #define    kScrollbarSize    15
  33.  
  34. pascal OSErr MyReceiveDropHandler(WindowPtr theWindow, unsigned long handlerRefCon,
  35.                                   DragReference theDrag);
  36. PROTO_UPP(MyReceiveDropHandler, DragReceiveHandler);
  37. pascal OSErr MyTrackingHandler(short message, WindowPtr theWindow,
  38.                                void *handlerRefCon, DragReference theDrag);
  39. PROTO_UPP(MyTrackingHandler, DragTrackingHandler);
  40.  
  41. static    void LocalToGlobalRgn (RgnHandle rgn);
  42. static    void OutlineRegion (RgnHandle theRgn);
  43.  
  44. void    MyDragInit(void)
  45. {
  46.     OSErr    err;
  47.     long    dragMgrAttr;
  48.     
  49.     err = Gestalt(gestaltDragMgrAttr, &dragMgrAttr);
  50.     gHaveDragMgr = (err == noErr) && (dragMgrAttr & (1L << gestaltDragMgrPresent)) != 0;
  51.     #ifdef powerc
  52.         gHaveDragMgr = gHaveDragMgr && 
  53.             (dragMgrAttr & (1L << gestaltPPCDragLibPresent)) != 0
  54.             && (Ptr)InstallTrackingHandler != kUnresolvedSymbolAddress;
  55.     #endif
  56.     
  57.     // If the DragManager is available, install our tracking handlers
  58.     if (gHaveDragMgr) {
  59.         err = InstallTrackingHandler(MyTrackingHandlerUPP, nil, nil);
  60.  
  61.         if (err == noErr) {
  62.             // If all is ok so far, install the rcv handler
  63.             err = InstallReceiveHandler(MyReceiveDropHandlerUPP, nil, nil);
  64.             if (err != noErr) {
  65.                 // If an error ocurred installing the rcv handler, remove the tracking handler
  66.                 RemoveTrackingHandler(MyTrackingHandlerUPP, nil);
  67.                 }
  68.             }
  69.         
  70.         // If any error occurred, turn off DragManager support    
  71.         if (err != noErr) {
  72.             gHaveDragMgr = false;
  73.             }
  74.         }
  75. }
  76.  
  77. /*    MyReceiveDropHandler
  78.  *    Called by the Drag Manager when a drop occurs over one of Telnet's windows. */
  79. SIMPLE_UPP(MyReceiveDropHandler, DragReceiveHandler);
  80. pascal OSErr MyReceiveDropHandler(WindowPtr theWindow, unsigned long handlerRefCon,
  81.                                   DragReference theDrag)
  82. {    
  83.     OSErr                result;
  84.     Handle                dataH;
  85.     unsigned short        items, index;
  86.     ItemReference        theItem;
  87.     DragAttributes        attributes;
  88.     Size                textSize;
  89.     short                mouseDownModifiers, mouseUpModifiers;
  90.     WindRecPtr            tw;
  91.  
  92.     if (!gDropcanAcceptItems || !gDropcursorInContent)
  93.         return(dragNotAcceptedErr);
  94.  
  95.     SetPort(theWindow);
  96.  
  97.     // No text yet
  98.     dataH = nil;
  99.     
  100.     GetDragAttributes(theDrag, &attributes);
  101.     GetDragModifiers(theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers);
  102.  
  103.     //    Loop through all of the drag items contained in this drag and collect the text
  104.     //    into the accumulation handle.
  105.  
  106.     CountDragItems(theDrag, &items);
  107.  
  108.     for (index = 1; index <= items; index++) {
  109.         //    Get the item's reference number, so we can refer to it.
  110.         GetDragItemReferenceNumber(theDrag, index, &theItem);
  111.  
  112.         //    Try to get the flags for a 'TEXT' flavor. If this returns noErr,
  113.         //    then we know that a 'TEXT' flavor exists in the item.
  114.         result = GetFlavorDataSize(theDrag, theItem, 'TEXT', &textSize);
  115.  
  116.         if (result == noErr) {
  117.             if (dataH == nil) {                    // No data yet, create a new handle for accumulation
  118.                 dataH = NewHandle(textSize);
  119.                 if (dataH == nil) {
  120.                     return memFullErr;            // Exit if there is an error
  121.                     }
  122.                 }
  123.             else {                                // Append to existing TEXT data
  124.                 SetHandleSize(dataH, GetHandleSize(dataH) + textSize);    // Grow the handle
  125.                 if (MemError() != noErr) {
  126.                     return memFullErr;            // Exit if there is a problem
  127.                     }
  128.                 }
  129.                 
  130.  
  131.             // Temporarily lock down the accumlation handle
  132.             HLock(dataH);
  133.         
  134.             // Get the drag data    
  135.             GetFlavorData(theDrag, theItem, 'TEXT', *dataH, &textSize, 0L);
  136.  
  137.             // Ok to unlock the accumulation handle
  138.             HUnlock(dataH);
  139.             }
  140.         }
  141.  
  142.     // Get the length of all that was accumulated
  143.     textSize = GetHandleSize(dataH);
  144.  
  145.     //    If we actually received text, insert it into the destination.
  146.     if (textSize != 0) {
  147.         if (attributes & dragHasLeftSenderWindow) {
  148.             HideDragHilite(theDrag);
  149.             }
  150.  
  151.         HLock(dataH);
  152.  
  153.         // Send the text to the window.        
  154.         tw = WindowPtr2WindRecPtr(theWindow);
  155.         if (tw != nil) {
  156.             SendStringAsIfTyped(tw, *dataH, textSize);
  157.             }
  158.         HUnlock(dataH);
  159.         }
  160.  
  161.     if (dataH != nil) {
  162.         DisposeHandle(dataH);
  163.         }
  164.  
  165.     return(noErr);
  166. }
  167.  
  168. /*    MyTrackingHandler
  169.  *    This is the drag tracking handler for windows in the DragText application.*/
  170. SIMPLE_UPP(MyTrackingHandler, DragTrackingHandler);
  171. pascal OSErr MyTrackingHandler(short message, WindowPtr theWindow,
  172.                                void *handlerRefCon, DragReference theDrag)
  173. {
  174.     short                result;
  175.     unsigned short        count, index;
  176.     unsigned long        flavorFlags, attributes;
  177.     ItemReference        theItem;
  178.     RgnHandle            theRgn, selectionRgn;
  179.     Point                theMouse, localMouse;
  180.     Rect                dragRect;
  181.     GrafPtr                savePort;
  182.     Boolean                inOriginalSelection;
  183.     
  184.     if ((message != dragTrackingEnterHandler) && (!gDropcanAcceptItems))
  185.         return(noErr);
  186.  
  187.     if ((message != dragTrackingEnterHandler) && (message != dragTrackingEnterWindow) 
  188.             && (!gDropDestCanAcceptItems))
  189.         return(noErr);
  190.  
  191.     GetDragAttributes(theDrag, &attributes);
  192.  
  193.     switch (message) {
  194.  
  195.         case dragTrackingEnterHandler:
  196.             //    We get called with this message the first time that a drag enters ANY
  197.             //    window in our application. 
  198.             gDropcanAcceptItems = true;
  199.                                         
  200.             //    Check to see if all of the drag items contain
  201.             //    TEXT. We only accept a drag if all of the items in the drag can be accepted.
  202.             CountDragItems(theDrag, &count);
  203.  
  204.             for (index = 1; index <= count; index++) {
  205.                 GetDragItemReferenceNumber(theDrag, index, &theItem);
  206.  
  207.                 result = GetFlavorFlags(theDrag, theItem, 'TEXT', &flavorFlags);
  208.  
  209.                 if (result != noErr) {
  210.                     gDropcanAcceptItems = false;
  211.                     break;
  212.                     }
  213.                 }
  214.             break;
  215.  
  216.         case dragTrackingEnterWindow:
  217.             //    We receive an EnterWindow message each time a drag enters one of our
  218.             //    application's windows. We initialize our global variables for tracking
  219.             //    the drag through the window.
  220.  
  221.             // Assume this window can accept the drag
  222.             gDropDestCanAcceptItems = true;
  223.             
  224.             // If it is not a connection window, it cannot accept a drop.
  225.             if (((WindowPeek)theWindow)->windowKind != WIN_CNXN) {
  226.                 gDropDestCanAcceptItems = false;
  227.                 break;
  228.                 }
  229.             
  230.             // Initially no blue box.
  231.             gDropcursorInContent = false;
  232.             break;
  233.  
  234.         case dragTrackingInWindow:
  235.             GetPort(&savePort);
  236.             SetPort(theWindow);
  237.  
  238.             //    We receive InWindow messages as long as the mouse is in one of our windows
  239.             //    during a drag. We draw the window highlighting when we get these messages.
  240.             GetDragMouse(theDrag, &theMouse, 0L);
  241.  
  242.             //    If we are still in the sender window, check to see if we should draw a blue box.
  243.             //    inOriginalSelection is true if the mouse is still within the confines of the
  244.             //    selected text's original location.  This allows the user to cancel a drop by
  245.             //    dropping the text somewhere inside of the original selection.
  246.             if (attributes & dragInsideSenderWindow) {
  247.                 localMouse = theMouse;
  248.                 GlobalToLocal(&localMouse);
  249.                 
  250.                 selectionRgn = RSGetTextSelRgn(WindowPtr2WindRecPtr(theWindow)->vs);
  251.                 inOriginalSelection = PtInRgn(localMouse, selectionRgn);
  252.                 DisposeRgn(selectionRgn);
  253.                 }
  254.             else {
  255.                 inOriginalSelection = false;
  256.                 }
  257.  
  258.             //    Show or hide the window highlighting when the mouse enters or leaves the
  259.             //    text area in our window (we don't want to show the highlighting when
  260.             //    the mouse is over the scroll bars).
  261.             dragRect = (*(((WindowPeek)theWindow)->contRgn))->rgnBBox;
  262.             
  263.             //    Subtract out the scrollbars.
  264.             dragRect.right -= kScrollbarSize;
  265.             dragRect.bottom -= kScrollbarSize;
  266.             
  267.             //    If the mouse is in the text area and not in the original selection,
  268.             //    draw the blue box.            
  269.             if (PtInRect(theMouse, &dragRect) && !inOriginalSelection) {
  270.                 if (!gDropcursorInContent) {
  271.  
  272.                     // Set up the blue box region.
  273.                     GlobalToLocal(&topLeft(dragRect));
  274.                     GlobalToLocal(&botRight(dragRect));
  275.                     RectRgn(theRgn = NewRgn(), &dragRect);
  276.  
  277.                     ShowDragHilite(theDrag, theRgn, true);
  278.  
  279.                     DisposeRgn(theRgn);
  280.                     }
  281.                     
  282.                 // Remember that we are in a valid drop location.
  283.                 gDropcursorInContent = true;
  284.  
  285.                 }
  286.             else {
  287.                 // We have moved out of a valid drop region.
  288.  
  289.                 if (gDropcursorInContent) {            // Hide the box if it was drawn.
  290.                     HideDragHilite(theDrag);
  291.                     }
  292.                     
  293.                 // Remember that we are outside of a valid drop region.
  294.                 gDropcursorInContent = false;
  295.  
  296.                 }    
  297.  
  298.             SetPort(savePort);
  299.             break;
  300.  
  301.         case dragTrackingLeaveWindow:
  302.                 HideDragHilite(theDrag);
  303.             break;
  304.  
  305.         case dragTrackingLeaveHandler:
  306.             break;
  307.  
  308.     }
  309.  
  310.     return(noErr);
  311. }
  312.  
  313. OSErr DragText(EventRecord *ev, Point where, short w, Boolean *dragged)
  314. {
  315.     DragReference    dragRef;
  316.     OSErr            err = noErr;
  317.     Boolean            haveDragRef = false;
  318.     RgnHandle        dragRgn = nil;
  319.     Handle            textH = nil;
  320.     long            size;
  321.     
  322.     *dragged = false;
  323.     if (!gHaveDragMgr) {
  324.         return noErr;
  325.         }
  326.         
  327.     dragRgn = RSGetTextSelRgn(w);
  328.     if (dragRgn == nil) {
  329.         return noErr;
  330.         }
  331.     if (!PtInRgn(where, dragRgn)) {
  332.         DisposeRgn(dragRgn);
  333.         return noErr;
  334.         }
  335.     if (!WaitMouseMoved(ev->where)) return noErr;
  336.     *dragged = true;
  337.  
  338.     textH = RSGetTextSel(w, 0);
  339.     
  340.     if ((textH == (char **)-1L) || (textH == nil)) {
  341.         textH = nil;
  342.         goto exit;
  343.         }
  344.     
  345.     HLock(textH);
  346.     size = GetHandleSize(textH);
  347.     
  348.     err = NewDrag(&dragRef);
  349.     if (err != noErr) goto exit;
  350.     haveDragRef = true;
  351.  
  352.     err = AddDragItemFlavor(dragRef, 1, 'TEXT', *textH, size, 0);
  353.     if (err != noErr) goto exit;
  354.  
  355.     LocalToGlobalRgn(dragRgn);
  356.     OutlineRegion(dragRgn);
  357.  
  358.     err = TrackDrag(dragRef, ev, dragRgn);
  359.     if (err != noErr && err != userCanceledErr) goto exit;
  360.  
  361.     DisposeRgn(dragRgn);
  362.     DisposeDrag(dragRef);
  363.     DisposeHandle(textH);
  364.     return noErr;
  365.     
  366. exit:
  367.  
  368.     if (haveDragRef) DisposeDrag(dragRef);
  369.     if (dragRgn != nil) DisposeRgn(dragRgn);
  370.     if (textH != nil) DisposeHandle(textH);
  371.     return err;
  372. }
  373.  
  374. static    void LocalToGlobalRgn (RgnHandle rgn)
  375. {
  376.     Point where;
  377.     
  378.     SetPt(&where, 0, 0);
  379.     LocalToGlobal(&where);
  380.     OffsetRgn(rgn, where.h, where.v);
  381. }
  382.  
  383. static    void OutlineRegion (RgnHandle theRgn)
  384. {
  385.     RgnHandle tempRgn;
  386.     
  387.     tempRgn = NewRgn();
  388.     CopyRgn(theRgn, tempRgn);
  389.     InsetRgn(tempRgn, 1, 1);
  390.     DiffRgn(theRgn, tempRgn, theRgn);
  391.     DisposeRgn(tempRgn);
  392. }
  393.